/*
 *------------------------------------------------------------------------
 *	COMMON.H
 *
 *	Contains definitions and prototypes common
 *	for all *.c files
 *
 *	Marcelo Walter
 *------------------------------------------------------------------------
 */

#ifdef GRAPHICS
	#include <forms.h>
#endif

#include <stdio.h>

/*
 *------------------------------------------------------------------------
 *	DEFINITIONS
 *------------------------------------------------------------------------
 */
#define X 		0
#define Y 		1
#define XY 		2

#define MINE_PI 3.141592654
#define	R		0
#define	G		1
#define B		2
#define	RGB		3

#define TRUE 		1
#define FALSE 		0

#define LINES      	1
#define BACKGROUND 	0

#define NCELLS 		200  	/* default number of cells in the domain */

/* Reminder: The current value for the maximum bucket size
   constrain the maximum number of cells to 10,000 */

#define BUCKET_SIZE_X	100	/* max domain size of bucket in X */
#define BUCKET_SIZE_Y	100	/* max domain size of bucket in Y */

#define MAX_X		200   	/* max x value for a cell position */
#define MAX_Y   	200   	/* max y value for a cell position */


#define NR 		18	/* default number of relaxation steps */
#define WD   	0.066   /* default weigth for the repulsive forces */
#define	WA		1.0	/* anisotropic weigth */


#define FINAL_TIME	10
#define TIME_UPDATE	10

#define	WRP		1.4	/* factor which multiplies the repulsive radius */

#define	HOW_MANY_TYPES	4	/* number of different types of cells */

#define COR_TYPE_C_R 	104	/* brown */
#define COR_TYPE_C_G	60
#define COR_TYPE_C_B	30

#define COR_TYPE_D_R	252 	/* yellow */
#define COR_TYPE_D_G	152
#define COR_TYPE_D_B	76

#define COR_TYPE_E_R 	216	/* buff */
#define COR_TYPE_E_G	112
#define COR_TYPE_E_B	32

#define COR_TYPE_F_R	255	/* white */
#define COR_TYPE_F_G	255
#define COR_TYPE_F_B	255


/* used with the heap functions */
#define HEAP_GROW_FACTOR 	100
#define FLOAT_MIN 		-1e20

#define FACTOR		5	/* factor for the points at
				   infinity in the voronoi */

#define	HOUR_CURSOR	1
/*
 *------------------------------------------------------------------------
 * 	DATA STRUCTURES
 *------------------------------------------------------------------------
 */
typedef unsigned char byte;
typedef enum{C, D, E, F}                            CELL_TYPE;
typedef enum{SPLIT, SWITCH, RELAX}	                 EVENT_TYPE;
typedef enum{PS, INTERNAL, SGI, BOTH}               OUTFILEMODE;
typedef enum{EXTERNAL, INTERACTIVE, NON_INTERACTIVE}INMODE;

typedef struct{
  short		color[RGB];
  float		prob;
  int		rateOfDivision;
}CTYPE;


/* CELL structure */
typedef struct cell{
  double      x,y,      	/* position of the cell */
              r,        	/* radius */
              fx,fy;    	/* force in x and y direction */
  CELL_TYPE   ctype;     	/* cell type */
  int         tsplit;		/* time for next mitosis to occur */
  byte 	      gen;			/* tells how many times the cell
								has divided itself */
  byte 	      border;		/* flags artificially inserted cells at
								the border. Test for Voronoi drawing */
  float	      adh[2][2];	/* adhesion between types of cells.
								BE CAREFUL MARCELO. THIS ONLY ALLOWS
								2 TYPES OF CELLS */
  struct cell *next;    	/* pointer to the next cell */
}CELL;


/* BUCKET structure */
typedef struct bucket{
  CELL *info;
  struct bucket *next;
}BUCKET;


/* Data structure for the voronoi part */
typedef struct{
  double     x, y;       	/* position of the Voronoi vertex */
  CELL       *sites[3];  	/* the sites that generate the Voronoi vertex */
}voronoiType;


typedef struct{
  int        faceSize;		/* How many points of vorPts are valid */
  int        vorPts[50];	/* The list of indices into the array of
                               voronoiType that form the boundary of the
                               face.  Note:  an index of 0 indicates
                               a Voronoi vertex at infinity! */
  CELL       *site;      	/* The cell that corresponds to the face. */
}faceType;

/* Holds an event structure */
typedef struct tevent{
  EVENT_TYPE whichEvent;
  float eventTime;
  CELL *info;
}EVENT;


typedef EVENT HEAP_ELEMENT;


typedef struct theap{
  EVENT *array;
  int   *p;
  int   *q;
  int   size;
  int   max;
}HEAP;


#ifdef __cplusplus
extern "C" {
#endif

/*
 *-----------------------------------------------------------------
 * 	PROTOTYPES
 *-----------------------------------------------------------------
 */

/* heap.c */
void HeapUp(HEAP *h, int k);
void HeapInsert(HEAP *h, EVENT *a);
void HeapGrow(HEAP *h, int grow);
HEAP *HeapInit(int size);
void HeapPrint(HEAP *h);
void HeapOrderPrint1(HEAP *h);
EVENT *HeapRemove(HEAP *h);
void HeapDown(HEAP *h, int k);
void EmptyHeap(HEAP *h);
HEAP *ClearHeap(HEAP *h);

/* util.c */
double fran(double min, double max);
int iran(int min, int max);
void save_ps_header(FILE *fp, int np);
int mypoidev(float xm,int *idum);
int polyCentroid(double x[], double y[], int n,
		double *xCentroid, double *yCentroid, double *area);
void errorMsg(char error_text[]);

/* list.c */
CELL *palloc(void);
void create_list(void);
void insert(CELL *p, CELL *h, CELL *t);
void print_list(CELL *h, CELL *t);
void remove_list(CELL *p, CELL *h);
void create_global_list(void);
void free_cells_list(void);

/* marcelo.c */
void getVoronoi(CELL *headCell, CELL *tailCell, 
           voronoiType **vorList, faceType **faceList, int *howManyVert);

/* voronoi.c */
void print_voronoi_faces_list(int np);
void computeVoronoi(void);
void add_points_at_infinity(void);
void remove_points_at_infinity(void);
void freeVoronoiSpace(void);
void add_cells_at_border(void);
void remove_cells_at_border(void);

/* main.c */
int main(int argc, char *argv[]);
CELL *create_cell(double x,double y,double r,CELL_TYPE t, byte g, byte b);
void init_param(void);
void init_ortcell(void);
CELL_TYPE pick_type(void);
void handles_output_file(char *out_file,  OUTFILEMODE mode);
void handles_input_file(char *inp_file);
void makes_all_cells(void);
void handle_split(CELL *s);
void print_info(void);
void update_relax_events_queue(int init_time, int final_time);
void update_split_events_queue( void );
void switch_cell(CELL *p, CELL_TYPE new_type);
void set_up(void);
void init_radius(void);
void check_limits_for_coordinates(double *px, double *py);
void inp_param(char *inp);
void init_data_struct(void);
CELL_TYPE sw_type(int type);
void rearrangeBuckets(void);
void fixCoordinates(double *x,  double *y);
void writeParamFile(char *out_file);
void compOrientation(void);
void aniso_effect(void);

/* RELAX.C */
void relaxation(int steps);
void compute_forces(CELL *s, double *sumdx, double *sumdy);
int force(CELL *s, CELL_TYPE ttype, double xt, double yt, double *dxi, double *dyi);
void checkBuckets(CELL *s,  int cbx,  int cby);
void compute_forces_v(CELL *s, double *sumdx, double *sumdy);

/* BUCKET.C */
void create_bucket_list(void);
BUCKET *balloc(void);
void insert_bucket(BUCKET *p, BUCKET *h, BUCKET *t);
void remove_bucket(BUCKET *p, BUCKET *h, BUCKET *t);
void print_bucket_list(BUCKET *h, BUCKET *t);
void free_buckets_list(int sx, int sy);
void assign_buckets(void);
void print_buckets(int sx, int sy);
void findBucket(double x, double y, int *ix, int *iy);

/* RANDOM.C */
float ran1(int *idum);
float poidev(float xm,int *idum);

#ifdef GRAPHICS
/* GRAPH.C */
void getinput();
void init_devices(void);
void init_graphics(double xf, double yf);
void find_cell(double x, double y);
void drawVoronoi(int nsites, byte mode);
void display1(double r);
void display(byte mode);
void draw_borders(void);
void black_out(void);
void draw_cell_filled(CELL *s, int i);
void output_view_window_as_rgb (char *file_name);

/* INTERFACE.C */
void initing(FL_OBJECT *obj, long foo);
void set_mode(FL_OBJECT *obj, long foo);
void set_aging(FL_OBJECT *obj, long foo);
void set_voronoi(FL_OBJECT *obj, long foo);
void relaxing(FL_OBJECT *obj, long foo);
void exiting(FL_OBJECT *obj, long foo);
void set_active_types(FL_OBJECT *obj, long t);
void ps_options(FL_OBJECT *obj, long foo);
void set_division(FL_OBJECT *obj, long t);
void set_prob(FL_OBJECT *obj, long t);
void set_new_type(FL_OBJECT *obj, long t);
void set_forms_inputs(FL_OBJECT *obj, long what);
void saving(FL_OBJECT *obj, long foo);
void loading(FL_OBJECT *obj, long foo);
void starting(FL_OBJECT *obj, long foo);
void change_adhesion(FL_OBJECT *obj, long foo);
void switch_type(FL_OBJECT *obj, long foo);
void set_adhesion(FL_OBJECT *obj, long what);
void set_switching(FL_OBJECT *obj, long what);
void set_outmode(FL_OBJECT *obj,long mode);
void init_the_forms(void);
void simulation(void);
void update_individual_number_of_cells(void);
void updateForms(void);

#else
/* AUXILIO.C */
void simulation(void);
void exiting();
void initing(INMODE mode, char *inp);
void writeOutputFile(OUTFILEMODE mode, char *psFileName, char *intFileName);
#endif

#ifdef __cplusplus
}
#endif
